

// 什么是Segmentation fault呢？
// 翻译就是段错误。所谓的段错误就是指访问的内存超过了系统所给这个程序的内存空间，
// 通常这个值是由gdtr来保存的，他是一个48位的寄存器，其中的32位是保存由它指向的gdt表，后13位保存相应于gdt的下标，
// 最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表，
// 在这张表中就保存着程序运行的代码段以及数据段的起始地址以及相应的断限和页面交换还有程序运行级别和内存粒度等信息，
// 一旦一个程序发生了越界访问，CPU就会产生相应的异常保护，于是segmentation fault就出现了。

// 解决方法：
// 1. 利用gdb逐步查找段错误 ---> 得会用gdb调试
// 2. 分析core文件 ---> gdb ./test core.4244
// 3. 段错误时启动调试
// 4. 利用backtrace和objdump进行分析

// test1:
// #include <stdio.h>
// int  main(void){
//     char test[1];
//     printf("%c", test[10]);
//     return 0;
// }
// 这就是明显的数组越界了，或者这个地址根本不存在。

// test2:
// #include <stdio.h>
// int main(void){
//     int* p = NULL;
//     // *p = 1;                  // Segmentation fault
//     // printf("%d\n", *p);      // Segmentation fault
//     return 0;
// }

// test3:
// #include <stdio.h>
// int  main(void){
//     char test[1];
//     printf("%s", test[10]);     // segmentation fault
//     return 0;
// }

// test4:
// 仔细看看，发现了这样一个问题，在打印字符串的时候，实际上是打印某个地址开始的所有字符，但是当你想把整数当字符串打印的时候，
// 这个整数被当成了一个地址，然后printf从这个地址开始去打印字符，直到某个位置上的值为\0。所以，如果这个整数代表的地址不存在或者不可访问，
// 自然也是访问了不该访问的内存——segmentation fault。
// ​ ​类似的，还有诸如：sprintf等的格式控制问题，比如，试图把char型或者是int的按照%s输出或存放起来，如：
// #include <stdio.h>
// #include <string.h>
// int main(void){
//     char c = 'c';
//     int i = 10;
//     char buf[100];
//     printf("%s", c);        // 试图把char型按照字符串格式输出，这里的字符会解释成整数，再解释成地址，所以原因同上面那个例子
//     printf("%s", i);            // 试图把int型按照字符串输出
//     memset(buf, 0, 100);
//     sprintf(buf, "%s", c);    // 试图把char型按照字符串格式转换
//     memset(buf, 0, 100);
//     sprintf(buf, "%s", i);   // 试图把int型按照字符串转换
//     return 0;
// }

// ————————————————————————————————————————————————————————————————————————————————————————————————————

// test5:
// #include <stdio.h>
// #include <string.h>
// int main(void){
//     char* str1 = "Wang";
//     char* str2 = "Lei";
//     printf("%s\n", strcat(str1, str2));
//     return 0;
// }

// test6:  往受到系统保护的内存地址写数据
// #include <stdio.h>
// int main(void){
//     int i = 0;
//     scanf("%d", i);      // i == 0, 所以这一行表示的意思就是往 0 地址处写入数据
//     printf("%d\n", i);
//     return 0;
// }
// test7:
// #include <stdio.h>
// int main(void){
//     char* p;
//     p = NULL;
//     *p = 'x';      // 这个例子也是试图往内存地址0处写东西
//     printf("%c\n", *p);
//     return 0;
// }
// test8:
// #include <stdio.h>
// #include <string.h>
// void dummy_function(void){
//     unsigned char* ptr = 0x00;
//     *ptr = 0x00;    // 这个例子也是试图往内存地址0处写东西
// }
// int main(void){
//     dummy_function();
//     return 0;
// }

// test9: 内存越界(数组越界，变量类型不一致等)
// #include <stdio.h>
// int main(void){
//     char test[1];
//     printf("%c\n", test[1000000]);
//     return 0;
// }

// test10:
// [trw@VM-4-5-centos test]$ make
// gcc -o test test2.c -g    # -g3 也是可以的
// /lib/../lib64/crt1.o: In function `_start':
// (.text+0x20): undefined reference to `main'
// collect2: error: ld returned 1 exit status
// make: *** [test] Error 1
// #include <stdio.h>
// int mian(void){
//     int b = 10;
//     printf("%s\n", b);
//     return 0;
// }

// ————————————————————————————————————————————————————————————————————————————————————————————————————————

// 安装C/C++语法快捷键：C/C++ for Visual Studio Code
// 去官网：https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools
// 下载插件扩展到本地
// 再去从 VSIX 安装(显示本地)
// 再重新链接一个服务器就可以了
